using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GarageGames.Torque.Util
{
    public class ListUtils
    {
        public delegate bool ConditionalDelegate(object someObject);

        /// <summary>
        /// This method returns the first item in a List<T> that matches the condition
        /// passed in as a delegate.
        /// </summary>
        /// <param name="theList"></param>
        /// <param name="theCondition"></param>
        /// <returns></returns>
        public static T Find<T>(List<T> theList, ConditionalDelegate theCondition)
        {
            // Iterate over the objects in the list
            int count = theList.Count;

            for (int i = 0; i < count; i++)
            {
                // Test the condition.
                if (theCondition(theList[i]))
                {
                    // We found a match. Return it.
                    return theList[i];
                }
            }

            // No match was found, return the default for this class.
            return default(T);
        }

        /// <summary>
        /// This method removes all elements in a List<T> that match the condition
        /// passed in as a delegate.
        /// </summary>
        /// <param name="theList">The list to be trimmed</param>
        /// <param name="theCondition">The condition that tells which items to remove</param>
        /// <returns>The number of removed items</returns>
        public static int RemoveAll<T>(List<T> theList, ConditionalDelegate theCondition)
        {
            // Create a temporary list to store the objects that must
            // be removed. This is necessary because you cannot modify
            // a list while using it as a loop control.
            List<T> removals = new List<T>();

            // Iterate over the list
            for (int i = 0; i < theList.Count; i++)
            {
                // Check the condition
                if (theCondition(theList[i]))
                {
                    // Tag this object for removal
                    removals.Add(theList[i]);
                }
            }

            // Remove all the elements from the list that match the condition.
            for (int i = 0; i < removals.Count; i++)
            {
                // Remove each object from the source list
                theList.Remove(removals[i]);
            }

            // Return the number of removals
            return removals.Count;
        }

        /// <summary>
        /// This method will return all items in a List<T> that match the condition
        /// passed in as a delegate.
        /// </summary>
        /// <param name="theSource"></param>
        /// <param name="theCondition"></param>
        /// <returns></returns>
        public static List<T> FindAll<T>(List<T> theSource, ConditionalDelegate theCondition)
        {
            // Define a list to store the matches
            List<T> result = new List<T>();

            // Iterate over the list
            for (int i = 0; i < theSource.Count; i++)
            {
                // Check the condition
                if (theCondition(theSource[i]))
                {
                    // Add this item to the result list
                    result.Add(theSource[i]);
                }
            }

            // Return the result list
            return result;
        }
    }
}
